﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: StoredProcedureCommandBuilder.cs
//
//  Description: Converts a StoredProcedureQuery to a storage command.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using Chili.Opf3.Storages;
using System.Data;

namespace Chili.Opf3.Query.StoredProcedures
{
	/// <summary>
	/// This class converts a <see cref="StorageProcedureQuery">StorageProcedureQuery</see>
	/// into a storage dependent command.
	/// </summary>
	public sealed class StoredProcedureCommandBuilder : IStorageCommandBuilder
	{
		#region IStorageCommandBuilder Members

		/// <summary>
		/// Converts the given query to a storage dependent <see cref="Opf3.Query.CompiledQuery">CompiledQuery</see>. 
		/// This method should only be called by a class that implements the <see cref="IQuery">IQuery</see> 
		/// interface.
		/// </summary>
		/// <param name="query"><see cref="Opf3.Query.IQuery">Query</see> object
		/// that is converted to a storage dependent <see cref="Opf3.Query.CompiledQuery">CompiledQuery</see>.
		/// </param>
		/// <param name="storage">The storage that the query is compiled for.</param>
		/// <returns>A storage dependent <see cref="Opf3.Query.CompiledQuery">CompiledQuery</see>.</returns>
		public CompiledQuery ToCompiledQuery(IStorage storage, IQuery query)
		{
			if (storage == null)
				throw new ArgumentNullException("storage");
			if (query == null)
				throw new ArgumentNullException("query");
			StoredProcedureQuery sq = query as StoredProcedureQuery;
			if (sq == null)
				throw new NotSupportedException("Only SqlQuery supported by this class.");
			SqlStorageBase ssb = storage as SqlStorageBase;
			if (ssb == null)
				throw new NotSupportedException("Only classes that inherit from SqlStorageBase are supported by this class.");

			// create a command object.
			IDbCommand command = ssb.CreateCommand();
			if (command == null)
				throw new NullReferenceException("Storage returned null for command.");
			command.CommandType = CommandType.StoredProcedure;
			command.CommandText = sq.StoredProcedureName;

			foreach (StoredProcedureNamedParameter p in sq.Parameters)
			{
				string name = p.Name;

				IDataParameter parameter = ssb.CreateParameter(0, ref name, p.Value, p.Type);

				command.Parameters.Add(parameter);
			}

			CompiledQuery cq = new CompiledQuery(command, query.QueryType);
			cq.Timeout = sq.Timeout;
			return cq;
		}

		/// <summary>
		/// Returns whether the <see cref="IStorageCommandBuilder">IStorageCommandBuilder</see> supports 
		/// the query type on the given storage.
		/// </summary>
		/// <param name="storage">The storage for which the query should be compiled.</param>
		/// <param name="query">The query that should be compiled to a storage dependent command.</param>
		/// <returns>True if the query can be parsed by the <see cref="IStorageCommandBuilder">IStorageCommandBuilder</see>.</returns>
		public bool IsSupported(IStorage storage, IQuery query)
		{
			return (storage is SqlStorageBase && query is StoredProcedureQuery);
		}

		#endregion
	}
}
